/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pr3.cruce;

import java.util.List;
import pr3.cromosoma.CromosomaArbol;
import pr3.cromosoma.Utilidades;
import pr3.funcion.Funcion;

/**
 *
 * @author Gonzalo Ortiz Jaureguizar (gortiz at software.imdea.org)
 */
public class CruceCromosomaArbol extends EstrategiaCruce<CromosomaArbol> {

    final int profMax;

    public CruceCromosomaArbol(int profMax) {
        this.profMax = profMax;
    }
    
    public void cruce(List<CromosomaArbol> seleccionado, double probCruce, List<CromosomaArbol> hijos) {
        for(CromosomaArbol c : seleccionado) {
            assert(c.getProfundidad() <= profMax);
        }
    }

    @Override
    protected void cruzar(CromosomaArbol p1, CromosomaArbol p2, CromosomaArbol h1, CromosomaArbol h2) {
        cruzar(p1, p2, h1);
        cruzar(p2, p1, h2);
    }
    
    private void cruzar(CromosomaArbol p1, CromosomaArbol p2, CromosomaArbol h) {
        h.copia(p1);
        
        //primero seleccionamos el nodo que añadiremos
        Funcion f2 = Utilidades.getNodoAleatorio(p2).clone(); //clonamos para no modificar al padre
        
        int profMaxF1 = profMax - f2.getProfundidadSubarbol(); //para evitar pasarnos de profundidad
        
        //luego seleccionamos el nodo que remplazaremos
        Funcion f1 = Utilidades.getNodoAleatorio(h, profMaxF1);
        int test = f1.getProfundidad() + f2.getProfundidadSubarbol();
        int test2 = f1.getProfundidadSubarbol() + f2.getProfundidad();
        int arg1 = -1;
        for (int i = 0; i < f1.getPadre().getAridad(); i++) {
            if (f1.getPadre().getArgumento(i) == f1) {
                arg1 = i;
            }
        }

        //finalmente los cruzamos
        f1.getPadre().setArgumento(arg1, f2);
        f2.setPadre(f1.getPadre());
        
        assert (h.getProfundidad() <= profMax) : "Arbol de profundidad excesiva (" + h.getProfundidad() + " "+test+" "+test2+")";
    }
}